using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.SceneManagement;
using UnityEngine;
using Object = UnityEngine.Object;
using Framework.EditorDependency;

namespace Framework.Editor
{
    public static class DoDoveCreatePrefab
    {
        private static readonly string NamespaceStr =
            Resources.Load<DoDoveUIConfig>("FrameWorkConfig/DoDoveUIConfig").namespaceStr;
        
        private static string _scriptPath =>
            Resources.Load<DoDoveUIConfig>("FrameWorkConfig/DoDoveUIConfig").scriptPath;

        private static string _prefabPath =>
            Resources.Load<DoDoveUIConfig>("FrameWorkConfig/DoDoveUIConfig").prefabPath;

        private static Dictionary<string, string> _namespaceStr = new Dictionary<string, string>();
        
        private static void SetCurSelectToPanel()
        {
            var curScene = EditorSceneManager.GetActiveScene();

            if (curScene.isDirty)
            {
                // 保存当前场景
                if (!EditorSceneManager.SaveScene(curScene))
                {
                    Debug.LogError("场景保存失败--返回");
                    return;
                }
            }

            var gos = curScene.GetRootGameObjects();
            GameObject curCanvas = null;
            foreach (var go in gos)
            {
                if (go.name == "Canvas")
                {
                    curCanvas = go;
                }
            }

            if (curCanvas == null)
            {
                Debug.Log(curScene.name + "--不存在Canvas节点");
                return;
            }

            Transform panel = curCanvas.transform.Find("Panel");

            if (panel == null)
            {
                Debug.Log(curScene.name + "--Canvas下不存在panel");
                return;
            }

            //指定激活的panel
            Selection.activeGameObject = null;
            Selection.activeGameObject = panel.gameObject;
        }

        private static void CreateScript()
        {
            _namespaceStr.Clear();
            SetCurSelectToPanel();

            if (!Directory.Exists(_scriptPath))
            {
                Directory.CreateDirectory(_scriptPath);
                Debug.Log("不存在" + _scriptPath + "--创建");
            }

            Dictionary<string, string> attrInfos = new Dictionary<string, string>();

            var children = Selection.activeGameObject.GetComponentsInChildren<Transform>();
            foreach (var value in children)
            {
                var declearType = value.GetComponent<DodoveDeclearUIType>();
                if (declearType is not null)
                {
                    if (!attrInfos.ContainsKey(value.name))
                    {
                        attrInfos[value.name] = declearType.UIType;
                    }

                    if (declearType.UINamespace != "Default")
                    {
                        if (!_namespaceStr.ContainsKey(declearType.UINamespace))
                        {
                            _namespaceStr[declearType.UINamespace] = $"using {declearType.UINamespace};\n";
                        }
                    }
                }
                else
                {
                    if (!attrInfos.ContainsKey(value.name))
                    {
                        attrInfos[value.name] = "Transform";
                    }
                }
            }

            var curScene = EditorSceneManager.GetActiveScene();
            CreateScript_2(curScene.name, attrInfos);

            // 延迟编译触发
            EditorApplication.delayCall += () =>
            {
                AssetDatabase.SaveAssets();
                AssetDatabase.Refresh();
            };
        }

        private static readonly List<string> CommonUsings = new List<string>
        {
            "using UnityEngine;",
            "using UnityEngine.UI;"
        };

        private static void CreateScript_2(string className, Dictionary<string, string> attrInfos)
        {
            StringBuilder code = new StringBuilder();

            // 添加公共的using语句
            foreach (var usingStatement in CommonUsings)
            {
                code.AppendLine(usingStatement);
            }

            foreach (var namespaceStr in _namespaceStr)
            {
                code.Append(namespaceStr.Value);
            }

            code.Append("namespace " + NamespaceStr + "\n");
            code.Append("{\n");
            code.Append("\tpublic  class " + className + " :MonoBehaviour\n");
            code.Append("\t{\n");

            for (int i = 0; i < attrInfos.Count; i++)
            {
                KeyValuePair<string, string> attrInfo = attrInfos.ElementAt(i);

                code.Append("\t\t[SerializeField] public " + attrInfo.Value + " " + attrInfo.Key.Replace(" ", "_") +
                            ";\n");
            }

            code.Append("\t}\n");
            code.Append("}\n");
            string path = Path.Combine(_scriptPath, className + ".cs");

            try
            {
                File.WriteAllText(path, code.ToString());

                if (File.Exists(path))
                {
                    string assetsPath = Application.dataPath;
                    string relativePath = path.Substring(assetsPath.Length + 1);
                    relativePath = Path.Combine("Assets", relativePath);
  
                    AssetDatabase.ImportAsset(relativePath);

                    AssetDatabase.SaveAssets();
                    AssetDatabase.Refresh();
                    
                    Debug.Log("文件存在了");
                }
                else
                {
                    Debug.LogError("文件生成失败");
                }
            }
            catch (Exception e)
            {
                Debug.LogError("文件写入失败: " + e.Message);
            }
        }

        private static Type GetType(string scriptName)
        {
            Assembly assembly = System.Reflection.Assembly.Load("Assembly-CSharp");
            Type _type = assembly.GetType(scriptName);
            return _type;
        }

        private static void BindProperties()
        {
            var curScene = EditorSceneManager.GetActiveScene();
            string className = NamespaceStr + "." + curScene.name;
            Type scriptType = GetType(className);

            HashSet<string> boundProperties = new HashSet<string>();

            SetCurSelectToPanel();

            var obj = Selection.activeGameObject.GetComponent(scriptType);

            if (null == obj)
            {
                Selection.activeGameObject.AddComponent(scriptType);
                obj = Selection.activeGameObject.GetComponent(scriptType);
            }

            FieldInfo[] infos = scriptType.GetFields();


            int index = 0;
            var children = Selection.activeTransform.GetComponentsInChildren<Transform>();
            foreach (var child in children)
            {
                if (boundProperties.Contains(child.name))
                {
                    //绑定过了
                    continue;
                }


                boundProperties.Add(child.name);

                if (child.name == "Panel")
                {
                    infos[index].SetValue(obj, child);
                }
                else
                {
                    Type targetType = infos[index].FieldType;
                    var component = child.gameObject.GetComponent(targetType);
                    infos[index].SetValue(obj, component);
                }

                index += 1;
            }

            //重置下状态
            Selection.activeGameObject.SetActive(false);
            Selection.activeGameObject.SetActive(true);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();

            CreatePrefab();
        }

        private static void RemovePrefabDeclearComponent(GameObject prefab, string prefabPath)
        {
            if (prefab is not null)
            {
                var componentsInChildren = prefab.GetComponentsInChildren<DodoveDeclearUIType>();

                for (int i = 0; i < componentsInChildren.Length; i++)
                {
                    if (componentsInChildren[i] != null)
                    {
                        Object.DestroyImmediate(componentsInChildren[i]);
                    }
                }

                PrefabUtility.SaveAsPrefabAssetAndConnect(prefab, prefabPath, InteractionMode.AutomatedAction);
            }
            else
            {
                Debug.Log("prefab 是个空值");
            }
        }

        private static void CreatePrefab()
        {
            SetCurSelectToPanel();
            var curScene = EditorSceneManager.GetActiveScene();


            string prefabPath = Path.Combine(_prefabPath, curScene.name + ".prefab");
            //判断是否存在，存在先移除--保持干净
            if (!Directory.Exists(_prefabPath))
            {
                Directory.CreateDirectory(_prefabPath);
                Debug.Log("不存在" + _prefabPath + "--创建");
            }

            if (File.Exists(prefabPath))
            {
                File.Delete(prefabPath);
                Debug.Log("存在" + prefabPath + "--删除");
            }


            PrefabUtility.SaveAsPrefabAsset(Selection.activeGameObject, prefabPath);

            var prefab = PrefabUtility.LoadPrefabContents(prefabPath);

            RemovePrefabDeclearComponent(prefab, prefabPath);
        }

        public static void AutoCreatePrefab()
        {
            CreateScript();
            EditorPrefs.SetBool("IsAuto", true);
        }


        [DidReloadScripts]
        private static void AutoBindProperties()
        {
            bool IsAuto = EditorPrefs.GetBool("IsAuto");

            if (!IsAuto)
            {
                return;
            }

            //重置下初始状态
            EditorPrefs.SetBool("IsAuto", false);

            BindProperties();
        }
    }
}